#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAX 1024
#define SEP " "

enum redirect
{
	REDIR_NONE = 0,
	REDIR_OUTPUT,
	REDIR_INPUT,
	REDIR_APPEND
};

int split(char *command_str, char *argv[])
{
	assert(command_str);
	assert(argv);

	argv[0] = strtok(command_str, SEP);
	if(argv[0] == NULL)
		return -1;
	int i = 1;
	while(1)
	{
		argv[i] = strtok(NULL, SEP);
		if(argv[i] == NULL)
			break;
		++i;
	}
	return 0;
}

void debug_print(char *argv[])
{
	for(int i = 0; argv[i] != NULL; ++i)
	{
		printf("%d:%s\n", i, argv[i]);
	}
}

void show_env()
{
	extern char **environ;
	for(int i = 0; environ[i] != NULL; ++i)
	{
		printf("%d:%s\n", i + 1, environ[i]);
	}
}

int main()
{
	//自定义环境变量表
	char my_env[32][256];
	int env_index = 0;

	//上个进程的退出码
	int last_exit = 0;

	while(1)
	{
		printf("[chen@my_machine cur_path]# ");
		fflush(stdout);
		
		//获取输入的命令
		char command_str[MAX] = {0};
		char *s = fgets(command_str, sizeof(command_str), stdin);
		//abc\n\0
		command_str[strlen(command_str) - 1] = '\0';
		assert(s);
		
		//重定向符号判断
		char *redir_file = NULL;
		enum redirect redir_mode = REDIR_NONE;
		for(char *start = command_str; *start != 0; ++start)
		{
			//ls -a > file.txt
			if(*start == '>')
			{
				*start = '\0';
				++start;
				if(*start == '>')
				{
					*start = '\0';
					redir_mode = REDIR_APPEND;
				}
				else
				{
					redir_mode = REDIR_OUTPUT;
				}
				redir_file = start + 2;
			}

			//cat < file.txt
			if(*start == '<')
			{
				*start = '\0';
				redir_mode = REDIR_INPUT;
				redir_file = start + 2;
			}
		}

		//分割
		char *argv[MAX] = {NULL};
		int n = split(command_str, argv);
		if(n == -1)
			continue;

		//debug_print(argv);

		//bash自己执行的命令
		if(strcmp(argv[0], "cd") == 0)
		{
			if(argv[1] != NULL)
			{
				chdir(argv[1]);
			}
			continue;
		}
		else if(strcmp(argv[0], "export") == 0)
		{
			//需要开一块数据不会被轻易改变的空间
			if(argv[1] != NULL)
			{
				strcpy(my_env[env_index], argv[1]);
				putenv(my_env[env_index]);
				++env_index;
			}
			continue;
		}
		else if(strcmp(argv[0], "env") == 0)
		{
			show_env();
			continue;
		}
		else if(strcmp(argv[0], "echo") == 0)
		{
			//查看某一环境变量：echo $PATH
			//查看上一个进程的退出码： echo $?
			if(argv[1][0] == '$')
			{
				if(argv[1][1] == '?')
				{
					printf("%d\n", last_exit);
				}
				else
				{
					const char *target_env = getenv(argv[1] + 1);
					if(target_env != NULL)
					{
						printf("%s=%s\n", argv[1] + 1, target_env);
					}
				}
			}
			continue;
		}

		//给ls加上自动显示颜色参数
		if(strcmp(argv[0], "ls") == 0)
		{
			int i = 0;
			while(argv[i] != NULL)
			{
				++i;
			}
			argv[i] = (char*)"--color=auto";
			++i;
			argv[i] = NULL;
		}

		pid_t id = fork();
		assert(id >= 0);
		if(id == 0)
		{
			if(redir_mode == REDIR_OUTPUT)
			{
				
			}
			//child
			execvp(argv[0], argv);
			exit(-1);
		}

		int status = 0;
		pid_t ret = waitpid(id, &status, 0);
		if(ret > 0)
		{
			//对status位运算取得退出码
			last_exit = WEXITSTATUS(status);
		}
	}
}
